#include "stdafx.h"

#include "http.h"
#include "HttpServer.h"

size_t FindParam(const HttpHeader& r, const string& Param)
{
	for(size_t i = 0; i < r.dict.size(); i++)
	{
		string t1 = r.dict[i].first;
		string t2 = Param;
		if(t1.length() != t2.length())
		{
			continue;
		}
		for(size_t ii = 0; ii < t1.length(); ii++)
		{
			t1[ii] = (char)tolower(t1[ii]);
			t2[ii] = (char)tolower(t2[ii]);
		}
		if(t1 == t2)
		{
			return i;
		}
	}

	return (size_t)-1;
}
bool GetHeader(const HttpHeader& r,const string& Param,string& Value)
{
	size_t i = FindParam(r, Param);
	if(i == -1)
	{
		return false;
	}
	//cut spc
	Value.assign(r.dict[i].second.begin()+1,r.dict[i].second.end());
	return true;
}
void SetHeader(HttpHeader& r,const string& Param,const string& Value)
{
	size_t i = FindParam(r, Param);
	if(i == -1)
	{
		r.dict.push_back(make_pair(Param,Value));
		return;
	}
	//r.dict[i].second = Value;
	//add spc
	r.dict[i].second= " ";
	r.dict[i].second+= Value;
}

char* FormRequest(const HttpRequest& r)
{
	char* Buffer = new char[1024];
	
	size_t pos = 0;
	if(r.post)
	{
		pos = sprintf_s(Buffer,1024,"%s %s\r\n","POST",r.uri.c_str());
	}
	else
	{
		pos = sprintf_s(Buffer,1024,"%s %s HTTP/1.1\r\n","GET",r.uri.c_str());
	}
	
	for(vector<pair<string,string> >::const_iterator it = r.dict.begin();
		it!=r.dict.end();it++)
	{
		pos += sprintf_s(Buffer + pos,1024 - pos,"%s:%s\r\n",it->first.c_str(),it->second.c_str());
		
	}
	pos += sprintf_s(Buffer + pos,1024 - pos,"%s: %s\r\n","Host",r.host.c_str());

	sprintf_s(Buffer + pos, 1024-pos, "\r\n");
	
	return Buffer;

}

char* FormResponse(const HttpResponse& r)
{
	char *Buffer = new char[1024];
	size_t pos = 0;
	//GET /uri/uri/q
	/*if(r.post)
	{
		sprintf_s(Buffer,1024,"%s %s\r\n","POST",r.uri.c_str());
	}
	else
	{
		sprintf_s(Buffer,1024,"%s %s\r\n","GET",r.uri.c_str());
	}*/
	pos = sprintf_s(Buffer,1024,"%s %s\r\n", "HTTP/1.1", r.status.c_str());
	//cout << Buffer;
	//send(s,Buffer,strlen(Buffer),0);
	for(vector<pair<string,string> >::const_iterator it = r.dict.begin();
		it!=r.dict.end();it++)
	{
		pos += sprintf_s(Buffer + pos, 1024 - pos,"%s: %s\r\n",it->first.c_str(),it->second.c_str());
		//cout << Buffer;
		//send(s,Buffer,strlen(Buffer),0);
	}
	sprintf_s(Buffer + pos, 1024 - pos, "\r\n");
	//cout << Buffer;
	return Buffer;
}

bool  parseHttpResponse(char *pHdr, size_t hdrLen, HttpResponse& r)
{	
	if(pHdr == NULL)
	{
		abort();
		return false;
	}
	char *pLine = pHdr;
	char *pNext = NULL;

	size_t last = hdrLen - (sizeof(char) * 2);
	bool bFirstLine = true;

	while (true)
	{
		// Find the end of the current line, and the start of the next
		for (size_t n = 0; n <= last; n++)
		{
			if (pLine[n] == '\r' && pLine[n + 1] == '\n')
			{
				pLine[n] = 0;
				pLine[n + 1] = 0;
				pNext = pLine + n + 2;
				break;
			}
		}

		if (*pLine == 0)
		{	
			pLine = pNext;
			r.headerLength = pNext - pHdr;
			break;
		}
		string temp = pLine;
		if (bFirstLine)
		{
			r.status = temp;
			bFirstLine = false;
		}
		else
		{
			size_t sem = temp.find(':');
			if(sem == -1)
			{
				return false;
			}
			string k(temp.begin(),temp.begin()+sem);
			string v(temp.begin()+sem+1,temp.end());
			//r.dict[k] = v;
			r.dict.push_back(make_pair(k,v));

			if(k == "Content-Length")
			{
				r.contentLenght = atoi(v.c_str());
			}
		}

		pLine = pNext;
	}

	return true;
}

bool parseHttpRequest(char *pHdr, size_t hdrLen, HttpRequest& r)
{	
	char *pLine = pHdr;
	char *pNext = NULL;
	
	size_t last = hdrLen - (sizeof(char) * 2);
	bool bFirstLine = true;

	while (true)
	{
		// Find the end of the current line, and the start of the next
		for (size_t n = 0; n <= last; n++)
		{
			if (pLine[n] == '\r' && pLine[n + 1] == '\n')
			{
				pLine[n] = 0;
				pLine[n + 1] = 0;
				pNext = pLine + n + 2;
				break;
			}
		}

		if (*pLine == 0)
		{	
			pLine = pNext;
			break;
		}
		string temp = pLine;
		if (bFirstLine)
		{
			
			size_t len_spc = temp.find(' ');
			if(!len_spc)
			{
				return false;
			}
			const string method(temp.begin(),temp.begin()+len_spc);
			if(method == "POST")
			{
				r.post = true;
			}
			else if(method == "GET")
			{
				r.post = false;
			}
			else
			{
				return false;
			}
			size_t len = temp.find(':');
			if(len == -1)
			{
				//return false;
				size_t len_spc2 = temp.find(' ', len_spc + 1);
				if(len_spc2 == -1)
				{
					r.uri = string(temp.begin() + len_spc + 1, temp.end());
				}
				else
				{
					r.uri = string(temp.begin() + len_spc + 1, temp.begin() + len_spc2);
					r.httpVersion = string (temp.begin() + len_spc2 + 1, temp.end());
				}
				
				r.bProxyMode = false;
			}
			else
			{
				//for proxy mode
				const string proto(temp.begin()+ len_spc + 1, temp.begin() + len);
				if(proto != "http")
				{
					return false;
				}
				len+=2;//skip slashes

				size_t len2 = temp.find('/',len + 1);
				if(len2 == -1)
				{
					return false;
				}
				string adr(temp.begin() + len + 1,temp.begin()+len2);
				string uri(temp.begin() + len2,temp.end());
				r.uri = uri;
				size_t spc2 = uri.find(' ');
				if(spc2 == -1)
				{
					spc2 = uri.length();
				}
				r.uri_host.assign(uri.begin(), uri.begin() + spc2);
				//test
				//r.uri = r.uri_host;
				size_t sem = adr.find(':');
				if(sem != -1)
				{
					r.host.assign(adr.begin(),adr.begin()+ sem);
					string port(adr.begin()+sem + 1,adr.end());
					
					r.port = atoi(port.c_str());
				}
				else
				{
					r.host = adr;
					r.port = 80;
				}
				r.uri_host = r.host + r.uri_host;
			}
			bFirstLine = false;
		}
		else
		{
			size_t sem = temp.find(':');
			if(sem == -1)
			{
				return false;
			}
			string k(temp.begin(),temp.begin()+sem);
			string v(temp.begin()+sem+1,temp.end());
			//r.dict[k] = v;
			if(k == "Host")
			{
				r.host = v;
			}
			else
			{
				r.dict.push_back(make_pair(k,v));
			}			
			
		}

		pLine = pNext;
	}

	return true;
}

void* http_alloc(size_t size)
{
	return HttpServer::Alloc(size);
}

void http_free(void* mem)
{
	HttpServer::Free(mem);
}

char* http_strdup(const char* str)
{
	if(!str)
	{
		return NULL;
	}

	size_t len = strlen(str);
	char* buffer = (char*)HttpServer::Alloc(len);

	strcpy(buffer, str);

	return buffer;
}
wchar_t* http_wstrdup(const wchar_t* str)
{
	if(!str)
	{
		return NULL;
	}

	size_t len = wcslen(str);
	wchar_t* buffer = (wchar_t*)HttpServer::Alloc(len * sizeof(wchar_t));

	wcscpy(buffer, str);

	return buffer;
}